<!doctype html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport"
        content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <link rel="stylesheet" href="../../../resources/styles.css">
  <link rel="icon" type="image/x-icon" href="../../../resources/favicon.ico">
  <title>Tools Component</title>
  <style>
    body {
      margin: 0;
      padding: 0;
    }
    .full-screen {
      width: 100vw;
      height: 100vh;
      position: relative;
      overflow: hidden;
    }
  </style>
</head>
<body>
<div class="full-screen" id="container"></div>
<script type="importmap">
    {
      "imports": {
        "three": "https://unpkg.com/three@0.160.1/build/three.module.js",
        "stats.js/src/Stats.js": "https://unpkg.com/stats-js@1.0.1/src/Stats.js",
        "openbim-components": "../../../resources/openbim-components.js"
      }
    }
</script>
<script type="module">
	import Stats from 'stats.js/src/Stats.js';

	/*MD
  ### 🌍 Let's create a 3D world!
  ___
  The `SimpleScene` component is the easiest way to create a 3D space to start working.
  Let's start by importing Components and Three.js:
  */

	import * as THREE from 'three';
	import * as OBC from 'openbim-components';

	/*MD
  Now, the first step is getting a container for our viewer. 📦
  This is just a place where the 3D scene will be rendered.
  In this example we have just added an HTML `div` element with
  the ID `"container"`.
  */

	const container = document.getElementById('container');

	/*MD
	 Now, let's create an awesome 3D scene inside that HTML element! 🔥

  :::info Are you using a library/framework like React, Angular or vue?

  Then probably you have other mechanisms for getting a reference to the
  HTML div element. However you do it, as long as you get a reference
  in your code, you are good to go!

  :::

  ### 🧰 Setting up a components project
  ___
  Next, we will instantiate the main object of the library: **[Components](../api/classes/components.Components)**. 🤖
  This object will keep track of all the components that you create, making them
  easily accessible in all your application and making sure to update them
  in each frame, so you don't have to worry about that. 💪

  :::danger The minimum components application

  Any components app needs 4 things to work:
  - 🌍 A **[scene component](../api/classes/components.SimpleScene)** where our objects will live in 3D.
  - ⌚ A **[renderer component](../api/classes/components.SimpleRenderer)** that allows us to see things moving around.
  - 🎥 A **[camera component](../api/classes/components.SimpleCamera)** that defines where we are and in that 3D world.
  - ⚡ A **[raycaster component](../api/classes/components.SimpleRaycaster)** that makes it possible to interact with
  that 3D scene with our mouse / touch.

  :::
  */

	const components = new OBC.Components();
	components.scene = new OBC.SimpleScene(components);
	components.renderer = new OBC.SimpleRenderer(components, container);
	components.camera = new OBC.SimpleCamera(components);
	components.raycaster = new OBC.SimpleRaycaster(components);

	/*MD
  Now that everything is set up, let's start the app! You can do that with the `init` method.
  It will start updating all the components at 60 fps, so that you don't have to worry about the
  animation loop: 🚗💨💨💨
  */

	components.init();

	/*MD
  And that's it! You already have set up 3D scene that can run on any device. Easy, right? 🥳 But right now or scene
  is not very interesting, as it's only a infinite white void. Let's add some things to it! First, we need a reference
  to the scene, which you can get with the `get()` method. This method is present in all the components and is used to
  get the core of the component. We can do it like this:
  */

	const scene = components.scene.get();

	/*MD
	### 🎥 Adjusting scene and camera
  ___
  Great! Now we will locate the camera in a nice starting position. We can control the `SimpleCamera` component through its
  `controls` attribute. This object is an instance of the [camera-controls](https://github.com/yomotsu/camera-controls)
  library, which makes it super easy to control the camera in our 3D scene. We will set the position of the camera
  to `[10, 10, 10]` and make it look at the origin (`[0, 0, 0]`).
  */

	components.camera.controls.setLookAt(10, 10, 10, 0, 0, 0);

	/*MD
	### 🏀 Adding some 3D objects
  ___
  Awesome! We are now ready to start adding some objects. First, we will add a
  **[simple grid component](../api/classes/components.SimpleGrid)**. As the name implies, this component adds a simple
  2D grid to the scene that we can use as a reference.

  */

	const grid = new OBC.SimpleGrid(components);

  /*MD

  🚀 Also, let's add some real geometry to our small 3D app. All the components are built on top of
  [Three.js](https://threejs.org/), which means that Three.js code will work natively with them.
  This is great, because you can easily integrate components with any 3D app that you create.

  Let's try it by adding a simple cube:
  */

  const boxMaterial = new THREE.MeshStandardMaterial({ color: '#6528D7' });
  const boxGeometry = new THREE.BoxGeometry(3, 3, 3);
	const cube = new THREE.Mesh(boxGeometry, boxMaterial);
	cube.position.set(0, 1.5, 0);
	scene.add(cube);

	/*MD
	### 🔦 Lighting things up
  ___
  Of course, everything is black because we have no lights! Let's fix it by adding some basic illumination:
  */

	components.scene.setup();

	/*MD
  ### 🧹 Cleaning up
  ___
  As you might now, JavaScript has an automatic garbage collector that gets rid of the variables that you are no longer
  using. Unfortunately, that's not the case for
  [Three.js](https://threejs.org/docs/#manual/en/introduction/How-to-dispose-of-objects). But don't worry: components
  takes care of this for you. When you are finished working with a `Components` instance, simply call
  `components.dispose()` and we will clean everything up for you!

  :::caution Watch your variables!

  When you dispose the memory, make sure that you don't have any object or array referencing anything inside the
  `Components` instance or this won't work, because JavaScript will detect that you are still using it!

  :::

  :::tip Using React, Angular, Vue...?

  This topic is especially relevant in Single Page Application technologies because they never reload the page (which
  would release all the memory automatically). If you are using some of these, make sure that you set up the disposing
  logic to fire when you re-render the component that has the 3D app.

  :::

  And voilà! You have made your first 3D application using components. Easy, right? Of course, this is still far from a
  full-fledged BIM app, but don't worry! Keep following our tutorials and your app will go from zero to hero in no time! 🚀
  */

	const stats = new Stats();
	stats.showPanel(2);
	document.body.append(stats.dom);
	stats.dom.style.left = '0px';
	components.renderer.onBeforeUpdate.add(() => stats.begin());
	components.renderer.onAfterUpdate.add(() => stats.end());

</script>
</body>
</html>
